home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cuj9205.zip
/
1005016B
< prev
next >
Wrap
Text File
|
1992-06-02
|
2KB
|
106 lines
Listing 4 -- xstod.c
/* _Stod function */
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <locale.h>
#include <stdlib.h>
#include "xmath.h"
#define SIG_MAX 32
double _Stod(const char *s, char **endptr)
{ /* convert string to double, with checking */
const char point = localeconv()->decimal_point[0];
const char *sc;
char buf[SIG_MAX], sign;
double x;
int ndigit, nsig, nzero, olead, opoint;
for (sc = s; isspace(*sc); ++sc)
;
sign = *sc == '-' || *sc == '+' ? *sc++ : '+';
olead = -1, opoint = -1;
for (ndigit = 0, nsig = 0, nzero = 0; ; ++sc)
if (*sc == point)
if (0 <= opoint)
break; /* already seen point */
else
opoint = ndigit;
else if (*sc == '0')
++nzero, ++ndigit;
else if (!isdigit(*sc))
break;
else
{ /* got a nonzero digit */
if (olead < 0)
olead = nzero;
else /* deliver zeros */
for (; 0 < nzero && nsig < SIG_MAX; --nzero)
buf[nsig++] = 0;
++ndigit;
if (nsig < SIG_MAX) /* deliver digit */
buf[nsig++] = *sc - '0';
}
if (ndigit == 0)
{ /* set endptr */
if (endptr)
*endptr = (char *)s;
return (0.0);
}
for (; 0 < nsig && buf[nsig - 1] == 0; --nsig)
; /* skip trailing digits */
{ /* compute significand */
const char *pc = buf;
int n;
long lo[SIG_MAX/8+1];
long *pl = &lo[nsig >> 3];
static double fac[] = {0, 1e8, 1e16, 1e24, 1e32};
for (*pl = 0, n = nsig; 0 < n; --n)
if ((n & 07) == 0) /* start new sum */
*--pl = *pc++;
else
*pl = *pl * 10 + *pc++;
for (x = (double)lo[0], n = 0; ++n <= (nsig >> 3); )
if (lo[n] != 0)
x += fac[n] * (double)lo[n];
}
{ /* fold in any explicit exponent */
long lexp = 0;
short sexp;
if (*sc == 'e' || *sc == 'E')
{ /* parse exponent */
const char *scsav = sc;
const char esign = *++sc == '+' || *sc == '-'
? *sc++ : '+';
if (!isdigit(*sc))
sc = scsav; /* ill-formed exponent */
else
{ /* exponent looks valid */
for (; isdigit(*sc); ++sc)
if (lexp < 100000) /* else overflow */
lexp = lexp * 10 + *sc - '0';
if (esign == '-')
lexp = -lexp;
}
}
if (endptr)
*endptr = (char *)sc;
if (opoint < 0)
lexp += ndigit - nsig;
else
lexp += opoint - olead - nsig;
sexp = lexp < SHRT_MIN ? SHRT_MIN : lexp < SHRT_MAX
? (short)lexp : SHRT_MAX;
x = _Dtento(x, sexp);
return (sign == '-' ? -x : x);
}
}